import autoBind from 'class-autobind-decorator'
import { floor } from 'src/editor/math/base'
import { Surface } from 'src/editor/stage/render/surface'
import { createObjCache } from 'src/shared/utils/cache'
import { listen, listenOnce } from 'src/shared/utils/event'

export type IStageCursorType =
  | 'select'
  | 'move'
  | 'resize'
  | 'rotate'
  | 'add'
  | 'copy'
  | 'hand'
  | 'grab'

@autoBind
class StageCursorService {
  private type: IStageCursorType = 'select'
  private rotation = 0
  private locked = false

  initHook() {
    Surface.inited$.hook(() => this.setCursor('select'))
    listen('mouseup', () => (this.locked = false))
  }

  setCursor(type: IStageCursorType, rotation = 0) {
    if (this.locked) return this

    this.type = type
    this.rotation = floor(rotation)
    Surface.setCursor(this.getSvgUrl())
    return this
  }

  lock() {
    this.locked = true
    return this
  }

  unlock() {
    this.locked = false
    return this
  }

  upReset() {
    listenOnce('mouseup', () => {
      this.unlock().setCursor('select', 0)
    })
    return this
  }

  private svgCache = createObjCache<string>()

  private getSvgUrl() {
    return this.svgCache.getSet(`${this.type}-${this.rotation}`, () => {
      if (this.type === 'resize') {
        return `url('${URL.createObjectURL(
          new Blob([this.resizeSvg(this.rotation)], { type: 'image/svg+xml' })
        )}') 14 14, auto`
      }
      return `url('${URL.createObjectURL(
        new Blob([this[this.type]], { type: 'image/svg+xml' })
      )}') 5 5, auto`
    })
  }

  private select = `<svg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'>
    <path d='M9.61549 19.9233L5.35746 5.17568L19.0755 12.8854L13.1067 14.4694L12.9128 14.5209L12.8082 14.6922L9.61549 19.9233Z' fill='black' stroke='white'/>
    </svg>`

  private add = `<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M7.76817 10.1656H1.48969V8.10495H7.76817H8.26817V7.60495V0.995083H10.3416V7.60495V8.10495H10.8416H17.1083V10.1656L10.8416 10.1656H10.3416V10.6656V17.1562H8.26817V10.6656V10.1656H7.76817Z" fill="black" stroke="white"/>
    </svg>`

  private move = `<svg width="25" height="28" viewBox="0 0 25 28" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M9.14926 19.6541L4.89123 4.9065L18.6093 12.6162L12.6405 14.2003L12.4465 14.2517L12.342 14.4231L9.14926 19.6541Z" fill="black" stroke="white"/>
    <path d="M17.4758 20.3132H17.7258V20.0632V17.4717V17.2217H17.4758H16.224L18.4297 14.889L20.877 17.2217H19.3603H19.1103V17.4717V20.0632V20.3132H19.3603H22.2083H22.4583V20.0632V18.7423L24.4636 20.9264L22.4583 23.198V21.8341V21.5841H22.2083H19.3603H19.1103V21.8341V24.6133V24.8633H19.3603H20.6927L18.4249 26.8945L16.2727 24.8633H17.4758H17.7258V24.6133V21.8341V21.5841H17.4758H14.8325H14.5825V21.8341V23.2673L12.3508 21.0983L14.5825 18.7301V20.0632V20.3132H14.8325H17.4758Z" fill="black" stroke="white" stroke-width="0.5"/>
    </svg>`

  private hand = `<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M9.85661 6.87939V6.87939C10.3889 5.75929 11.983 5.75929 12.5153 6.87939V6.87939V5.57862V5.57862C12.9979 4.58502 14.4051 4.56171 14.9203 5.53877L14.9413 5.57862V6.87939V6.87939C15.271 5.76918 16.7528 5.55752 17.3939 6.52204V6.52204V8.59033V8.59033C17.7194 7.36088 19.4079 7.2153 19.9353 8.37261V8.37261V15.8463C19.9353 16.8212 19.5302 17.7524 18.8169 18.4171V18.4171C16.1596 20.8933 11.9871 20.7054 9.56302 18.0004L6.51778 14.6021C6.32942 14.392 6.20966 14.1293 6.17449 13.8493V13.8493C6.05669 12.9113 6.89101 12.1329 7.81855 12.3153L7.90016 12.3314C8.16734 12.3839 8.41428 12.5108 8.6126 12.6974L9.85661 13.8678V6.87939Z" fill="black"/>
    <path d="M12.5153 6.87939V6.87939C11.983 5.75929 10.3889 5.75929 9.85661 6.87939V6.87939V13.8678L8.6126 12.6974C8.41428 12.5108 8.16734 12.3839 7.90016 12.3314L7.81855 12.3153C6.89101 12.1329 6.05669 12.9113 6.17449 13.8493V13.8493C6.20966 14.1293 6.32942 14.392 6.51778 14.6021L9.56302 18.0004C11.9871 20.7054 16.1596 20.8933 18.8169 18.4171V18.4171C19.5302 17.7524 19.9353 16.8212 19.9353 15.8463V8.37261V8.37261C19.4079 7.2153 17.7194 7.36088 17.3939 8.59033V8.59033M12.5153 6.87939V11.3644M12.5153 6.87939V5.57862V5.57862C12.9979 4.58502 14.4051 4.56171 14.9203 5.53877L14.9413 5.57862V6.87939M14.9413 6.87939V6.87939C15.271 5.76918 16.7528 5.55752 17.3939 6.52204V6.52204V8.59033M14.9413 6.87939L14.9413 11.3644M17.3939 8.59033V11.3644" stroke="white" stroke-linecap="round"/>
    </svg>`

  private grab = `<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M9.85661 10.892L9.9459 10.6765C10.4154 9.54324 12.012 9.51927 12.5153 10.6379V10.6379V9.77025V9.77025C12.8969 8.67637 14.4456 8.68132 14.8203 9.77762L14.9413 10.1318V10.1318C15.3079 9.25923 16.4975 9.14405 17.0247 9.93008L17.3939 10.4805V10.892V10.892C17.7987 9.91693 19.1587 9.86039 19.6431 10.7985L19.9353 11.3644V15.8887C19.9353 16.8366 19.5415 17.7419 18.8479 18.3882V18.3882C16.2017 20.8541 12.028 20.594 9.70831 17.8186L7.60093 15.2972C7.45543 15.1231 7.35443 14.9162 7.3066 14.6945V14.6945C7.08464 13.6651 8.03581 12.7684 9.0503 13.0506L9.15004 13.0784C9.35423 13.1352 9.54363 13.2357 9.70514 13.3729L9.75356 13.414C9.79418 13.4486 9.85661 13.4197 9.85661 13.3664V10.892Z" fill="black"/>
    <path d="M12.5153 10.6379V10.6379C12.012 9.51927 10.4154 9.54324 9.9459 10.6765L9.85661 10.892V13.3664C9.85661 13.4197 9.79418 13.4486 9.75356 13.414L9.70514 13.3729C9.54363 13.2357 9.35423 13.1352 9.15004 13.0784L9.0503 13.0506C8.03581 12.7684 7.08464 13.6651 7.3066 14.6945V14.6945C7.35443 14.9162 7.45543 15.1231 7.60093 15.2972L9.70831 17.8186C12.028 20.594 16.2017 20.8541 18.8479 18.3882V18.3882C19.5415 17.7419 19.9353 16.8366 19.9353 15.8887V11.3644L19.6431 10.7985C19.1587 9.86039 17.7987 9.91693 17.3939 10.892V10.892M12.5153 10.6379L12.5153 11.3644M12.5153 10.6379V9.77025V9.77025C12.8969 8.67637 14.4456 8.68132 14.8203 9.77762L14.9413 10.1318M14.9413 10.1318V10.1318C15.3079 9.25923 16.4975 9.14405 17.0247 9.93008L17.3939 10.4805V10.892M14.9413 10.1318V11.3644M17.3939 10.892V11.3644" stroke="white" stroke-linecap="round"/>
    </svg>`

  private rotate = `<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M17.9707 7.24795L18.2712 7.59065L18.6402 7.32306L20.1869 6.20135L19.5201 10.8038L14.5657 10.4403L16.2 9.14298L16.6113 8.81652L16.2651 8.42172C15.4904 7.53823 14.5245 7.09714 13.4344 6.84246C12.3085 6.57941 11.1257 6.66971 10.0553 7.10094C8.98475 7.53223 8.07983 8.28319 7.47273 9.24854C6.86548 10.2141 6.58825 11.3435 6.68272 12.4739C6.77718 13.6043 7.23815 14.6745 7.99673 15.5312C8.7551 16.3876 9.77159 16.9864 10.8988 17.2442C12.026 17.502 13.2083 17.4061 14.2766 16.9698C15.1921 16.596 15.9848 15.988 16.5719 15.2125L18.405 16.288C17.5835 17.4239 16.4458 18.3175 15.1177 18.8598C13.6272 19.4685 11.9756 19.6027 10.4009 19.2426C8.82632 18.8826 7.41225 18.0474 6.36075 16.86C5.30945 15.6727 4.67444 14.1943 4.54437 12.6378C4.4143 11.0813 4.79554 9.52374 5.63512 8.18873C6.47484 6.85347 7.73058 5.80862 9.22392 5.20702C10.7174 4.60535 12.3697 4.47889 13.9425 4.84637C15.5153 5.21382 16.9252 6.05559 17.9707 7.24795Z" fill="black" stroke="white"/>
    </svg>`

  private copy = `<svg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
    <path d='M11.033 19.0965L7.21341 4.50721L20.9759 12.242L14.7155 13.9371L14.5379 13.9852L14.4338 14.137L11.033 19.0965Z' fill='black' stroke='white'/>
    <path d='M9.641 7.58417L17.054 11.8743L13.7069 12.789L11.7756 15.9271L9.641 7.58417Z' fill='white'/>
    <path d='M9.641 7.58417L17.054 11.8743L13.7069 12.789L11.7756 15.9271L9.641 7.58417Z' stroke='white'/>
    <path d='M6.79025 19.2755L2.53223 4.5279L16.2503 12.2376L10.2815 13.8217L10.0875 13.8731L9.98297 14.0445L6.79025 19.2755Z' fill='black' stroke='white'/>
    </svg>`

  private resizeSvg = (
    degree: number
  ) => `<svg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'>
    <path transform='rotate(${degree} 12.5 12.5)' d='M23.9611 11.8673L20.2565 16.2419V13.301V12.901H19.8565H12.4758H5.00089H4.60089V13.301V16.2169L1.02101 11.8627L4.60089 7.78206V10.6414V11.0414H5.00089H12.4758H19.6995H20.0995V10.6414V7.7337L23.9611 11.8673Z' fill='black' stroke='white' stroke-width='0.8'/>
    </svg>`
}

export const StageCursor = new StageCursorService()
